package com.lenovo.nova.widget;

import java.lang.reflect.Field;

import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.GridView;

import com.lenovo.nova.util.Applications;
import com.lenovo.nova.util.Applications.OnInputModeChangeListener;
import com.lenovo.nova.util.Applications.OnTouchBoardTouchedListener;
import com.lenovo.nova.util.debug.mylog;
import com.lenovo.nova.util.debug.slog;
import com.lenovo.nova.util.view.KeyUtil;
import com.lenovo.nova.utils.R;

@SuppressLint("NewApi")
public class CustomGridView extends GridView implements OnInputModeChangeListener, OnTouchBoardTouchedListener, OnScrollListener {
//	protected Rect mSelectorDrawRect;

    private static final boolean DEBUG = true;
    private static final String TAG = CustomGridView.class.getSimpleName();
    private Drawable mHoverDrawable;
    private Drawable mTopArrowDrawable;
    private Drawable mBottomArrowDrawable;

    private HelperForAbsListViewOnHover mHoverHelper = null;
	protected VerticalArrowBuilderHelper mArrowHelper = null;
    private boolean isVisibleToUser;

    public CustomGridView(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		initLayout();
	}

	public CustomGridView(Context context, AttributeSet attrs) {
		super(context, attrs);
        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.CustomListView);
        mTopArrowDrawable = a.getDrawable(R.styleable.CustomListView_topArrowDrawable);
        mBottomArrowDrawable = a.getDrawable(R.styleable.CustomListView_bottomArrowDrawable);
        mHoverDrawable = a.getDrawable(R.styleable.CustomListView_hoverDrawable);
		initLayout();
	}

	public CustomGridView(Context context) {
		super(context);
		initLayout();
	}

    public int getDistanceFromTop(int index){
        if(getChildAt(0) == null){
            return 0;
        }
        int row = index % getNumColumns() == 0 ? index / getNumColumns() + 1 : index / getNumColumns();
        int itemHeight = getChildAt(0).getHeight();
        int verticalSpace = getVerticalSpacing();

        int distance = row * itemHeight + (row - 1)* verticalSpace;
        mylog.i(TAG,"row " + row + " itemHeight " + itemHeight + " verticalSpace " + verticalSpace);
        return distance;
    }

	@Override
	public void onGlobalLayout() {
		super.onGlobalLayout();
        isVisibleToUser = isVisibleToUser();

        if(DEBUG)
            mylog.d(TAG,"onGlobalLayout isVisibleToUser " +  isVisibleToUser);


        if (mArrowHelper != null) {
            mArrowHelper.onGlobalLayout(isVisibleToUser);
        }

	}

	void initLayout() {
		setOnScrollListener(this);
		mHoverHelper = new HelperForAbsListViewOnHover(this);
		mArrowHelper = new VerticalArrowBuilderHelper(this);

		mHoverHelper.setHoverDrawable(onGetCustomSelectDrawable());

        if (Applications.get().isInTouchMode()) {
            setSelector(android.R.color.transparent);
        } else {
            setSelector(onGetCustomSelectDrawable());
        }
    }

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		switch (keyCode) {
		case KeyEvent.KEYCODE_DPAD_RIGHT:
			if (getSelectedItemPosition() < getCount() - 1 && getEndRowPos() == getSelectedItemPosition()) {
				// 原声的GridView不能自动换行
				setSelection(getSelectedItemPosition() + 1);
			}
			break;
		case KeyEvent.KEYCODE_DPAD_LEFT:
			if (getSelectedItemPosition() != 0 && getStartRowPos() == getSelectedItemPosition()) {
				// 原声的GridView不能自动换行
				setSelection(getSelectedItemPosition() - 1);
			}
			break;
		}

		return super.onKeyDown(keyCode, event);

	}

	public int getStartRowPos() {
		final int selectedPosition = getSelectedItemPosition();// mSelectedPosition;
		final int numColumns = getNumColumns();// mNumColumns;

		int startOfRowPos = (selectedPosition / numColumns) * numColumns;
		return startOfRowPos;
	}

	public int getEndRowPos() {
		return getStartRowPos() + getNumColumns() - 1;
	}

	@Override
	public boolean onHoverEvent(MotionEvent event) {
        if(DEBUG)
            mylog.d(TAG,"onHoverEvent");

        if(isVisibleToUser){
            if (mHoverHelper != null) {
                if (mHoverHelper.onHoverEvent(event)) {
                    return true;
                }
            }

            if (event.getAction() == MotionEvent.ACTION_HOVER_ENTER) {
                requestFocusFromTouch();
                requestFocus();
            }

        }

		return super.onHoverEvent(event);
	}

	@Override
	public void onTouchBoardTouched(KeyEvent event) {
        if(isVisibleToUser){
            if (event.getAction() == KeyEvent.ACTION_UP) {
                if (KeyUtil.isTouchBoardUp(event.getKeyCode())) {
                    smoothDown();
                }
                if (KeyUtil.isTouchBoardDown(event.getKeyCode())) {
                    smoothUp();
                }
            }

        }
	}

    @Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
        if(DEBUG)
            mylog.d(TAG,"onScrollStateChanged scrollState is " + scrollState);

        mArrowHelper.onScrollStateChanged(view, scrollState);
	}

	@Override
	public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

        isVisibleToUser = isVisibleToUser();

        if(DEBUG) {
            mylog.d(TAG, "onScroll firstVisibleItem " + firstVisibleItem + " visibleItemCount " + visibleItemCount + " totalItemCount " + totalItemCount);
        }
        if(isVisibleToUser){
            if (mArrowHelper != null) {
                mArrowHelper.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
            }

        }
	}

	@Override
	public void onInputModeChange(boolean isInTouchMode) {
		slog.d("SettingsCustomGridLayout onInputModeChange  onInputModeChange " + isInTouchMode);
		// mUiHelper
		if (mHoverHelper != null) {
			mHoverHelper.onInputModeChange(isInTouchMode);
		}
	}

	@SuppressLint("WrongCall")
	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		super.onLayout(changed, l, t, r, b);
        if(DEBUG)
            mylog.d(TAG,"onLayout");
        if(isVisibleToUser){
            if (mArrowHelper != null) {
                mArrowHelper.onLayout(changed, l, t, r, b);
            }

        }
	}

	@Override
	protected void onScrollChanged(int l, int t, int oldl, int oldt) {
        if(DEBUG)
            mylog.d(TAG,"onScrollChanged");

        if(isVisibleToUser){
            if (mHoverHelper != null) {
                mHoverHelper.onScrollChanged(l, t, oldl, oldt);
            }

            if (mArrowHelper != null) {
                mArrowHelper.onScrollChanged(l, t, oldl, oldt);
            }
        }
		super.onScrollChanged(l, t, oldl, oldt);
	}

	/**
	 * 
	 */
	protected void setScrollBar(AbsListView view) {
		Drawable track = onGetScrollBarTrack();
		Drawable thumb = onGetScrollBarThumb();
	
		try {
			Field field = getViewMScrollCacheField();
			Field scrollBarField = field.getType().getDeclaredField("scrollBar");
			scrollBarField.setAccessible(true);
			// ScrollBarDrawable
			Object scrollBarDraw = scrollBarField.get(field.get(view));
			// ScrollBarDrawable.class.getDeclaredMethod("setVerticalTrackDrawable",
			// Drawable.class).invoke(scrollBarDraw, track);
			// ScrollBarDrawable.class.getDeclaredMethod("setVerticalThumbDrawable",
			// Drawable.class).invoke(scrollBarDraw, thumb);
	
			// 在编译的时候，由于标准的SDK中没有ScrollBarDrawable 这个方法，可以通过反射来获取
			if(track != null){
				Class.forName("android.widget.ScrollBarDrawable").
				getDeclaredMethod("setVerticalTrackDrawable", Drawable.class).invoke(scrollBarDraw, track);
			}
			
			if(thumb != null){
				Class.forName("android.widget.ScrollBarDrawable").
				getDeclaredMethod("setVerticalThumbDrawable", Drawable.class).invoke(scrollBarDraw, thumb);
			}
	
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	protected Drawable onGetScrollBarThumb() {
		return getContext().getResources().getDrawable(R.drawable.png_scrollbar_thumb_vertical);
	}

	protected Drawable onGetScrollBarTrack() {
		return getContext().getResources().getDrawable(R.drawable.png_scrollbar_track_vertical);
	}

	@Override
	protected void initializeScrollbars(TypedArray a) {
		super.initializeScrollbars(a);
        if(DEBUG)
            mylog.d(TAG,"initializeScrollbars");
		setScrollBar(this);
	}

	@Override
	protected void onDraw(Canvas canvas) {
		super.onDraw(canvas);

		if (mHoverHelper != null) {
			mHoverHelper.draw(canvas);
		}
	
	}

	protected void onDrawVerticalScrollBar(Canvas canvas, Drawable scrollBar, int l, int t, int r, int b) {
		super.onDrawVerticalScrollBar(canvas, scrollBar, l, t, r, b);
	}

	@Override
	protected void onAttachedToWindow() {
        if(DEBUG)
            mylog.d(TAG,"onAttachedToWindow " + isVisibleToUser);

		SettingsApplication.get().addOnTochBoardTouchedListener(this);
		SettingsApplication.get().addOnInputModeChangeListener(this);
		if (mArrowHelper != null) {
			mArrowHelper.onAttachedToWindow();
		}

        if(mTopArrowDrawable != null){
            mArrowHelper.setTopArrowDrawable(mTopArrowDrawable);
        }

        if(mBottomArrowDrawable != null){
            mArrowHelper.setBottomArrowDrawable(mBottomArrowDrawable);
        }

		super.onAttachedToWindow();
	}

	protected Drawable onGetCustomSelectDrawable() {
        if(mHoverDrawable != null){
            return mHoverDrawable;
        }
		return new ColorDrawable(Color.YELLOW);

	}

	@Override
	protected void onDetachedFromWindow() {
        if(DEBUG)
            mylog.d(TAG,"onDetachedFromWindow");

		SettingsApplication.get().removeOnTouchBoardListener(this);
		SettingsApplication.get().removeOnInputChangeListener(this);
		if (mArrowHelper != null) {
			mArrowHelper.onDetachedFromWindow();
		}
		super.onDetachedFromWindow();
	}

	private void smoothDown() {
		mArrowHelper.nextSmoothScroll();
	
	}

	private void smoothUp() {
		mArrowHelper.lastSmoothScroll();
	}

	private Field getViewMScrollCacheField() {
		Field field = null;
		if (field == null) {
			try {
				field = View.class.getDeclaredField("mScrollCache");
				field.setAccessible(true);
			} catch (NoSuchFieldException e) {
				e.printStackTrace();
			}
		}
		return field;
	}

	private Field getAbsListViewField(String fieldName) {
		Field field = null;
		try {
			field = AbsListView.class.getDeclaredField(fieldName);
			field.setAccessible(true);
		} catch (NoSuchFieldException e) {
			e.printStackTrace();
		}
		return field;
	}

}
